Get better hardware. More RAM, faster disk.

Have a better schema. Move what ever is stored dynamically in secondary collection into MasterCollection so that you do not have to $lookup and then $merge.

Try removing the first $project.

For collections where you $lookup with foreignField:_id, reverse the process. Aggregate the secondary collection and then $merge like:

collection1.aggregate( [ { "$merge" : {
  "into" : "MasterCollection" , ...

You save on some $lookup and most likely you can avoid allowDiskUse for those.

Most likely you could also do the same with other collections by using:

on : [ "field1" , "field2" ]

But field1 and field2 would need to at the top level rather than within _id in secondary collections which you could do easily with a $set or $project.

I expect that starting the aggregate() on secondary to cut time in half as the number of $lookup is halved and in all cases disk would not be used.