Great question, very well presented.
In the bad old days of SQL 2000 I used to solve this sort of problem using sp_rename.
if exists (select * from sys.objects where type = 'U' and name = 'old_FD')
drop table old_FD
--code to create new_FD and populate it wit the replacement data
exec sp_rename 'FD', 'old_FD', 'OBJECT'
exec sp_rename 'new_FD','FD','OBJECT'
The SCH_M lock is held only for the duration of the two rename operations.
I did it this way because it didn't just work for tables, it worked for databases too - renaming databases is pretty quick; of course in the database, as opposed to table, case the create and populate bit was a transfer in to the server of a database created and validated elsewhere (transferred by DTS or snapshot replication or importing and restoring a backup, depending on the target server and what our access to it was like - internet between UK and 3rd world or developing countries was not always exactly brilliant) not something done in the same transaction as the renaming; some read-only (or read-only except when we wanted to replace them, to be precise) databases were better updated by that method than by updating data piecemeal - take the db describing available media directly off the QA server rather than using a script. And losing the old data only when the current data was out of date was to allow us to roll back to the previous state if the unthinkable happened and we had made an error in one of those releases (a symptom of my paranoia).