One method that I have used with great success is to use frames with a TPageControl and late bind my frames to the tPageControl the first time the page is selected.  This keeps the form load time down, by not creating frames which are never viewed, but yet allows the flexibility of being created, the state is maintained when changing between tabs.  Recently I switched to using forms and embedding them instead of frames...but the concept is the same.
The same can be done using a single "mount point" on a TTabControl and switching it out as the tab is changed, but then the issue of how to deal with the tab state as tabs are switched back too comes up.
[EDIT] The question comes up how do I handle communication between the frame and the parent form.  This actually is very easy to do using interfaces.  Just create a new unit that will be shared by the form AND the frame and add two interfaces:
type
  IFormInterface = interface
    [guid]
    procedure FormProc;
  end;
  IFrameInterface = interface
    [guid]
    procedure SetFormController(Intf:IFormInterface);
  end;
Have the form implement the IFormInterface, and the frame implement the IFrameInterface.  When you click on a tab and show a frame, then run code like the following:
var
  FrameIntf : IFrameInterface;
begin
  if Supports(FrameObj,IFrameINterface,FrameIntf) then
    FrameIntf.SetFormController(Self);
end;
your frame implementation of the SetFormController method would then hold onto the reference passed, which would allow it to call upwards into the form. 
procedure TFrame1.SetFormController(Intf:IFormInterface);
begin
  fFormController := Intf;
end;
Procedure TFrame1.Destroy; override;
begin
  fFormController := nil;  // release the reference
  inherited;
end;
Procedure TFrame1.Button1Click(Sender:tObject);
begin
  if fFormController <> nil then
    fFormController.FormProc
  else
    Raise Exception.Create('Form controller not set');
end;