If You want something more flexible, You can use class objects to create any object derived from TClass1. But it requires that all constructors have same list of parameters. Here is a sample code:
[pascal]

type
TClass1 = class;
TClass1Object = class of TClass1; //a class object (metaclass)

TClass1 = class(TObject)
...
constructor Create;
function AddIt(classType : TClass1Object): TClass1;
...
end;

TClass2 = class(TClass1)
...
constructor Create; //must have same signature as TClass1.Create
end;

...

function TClass1.AddIt(classType : TClass1Object): TClass1;
begin
Result := classType.Create;
FList.Add(Result)
end;

...

var
C: TClass1;
begin
C := TClass1.Create();
try
C.X := 3.14;
with C.AddIt(TClass2) as TClass2 do
begin
X := 5.25;
WriteVal();
end;
finally
FreeAndNil(C);
end;

readln;
end.
[/pascal]