The lines you showed are using the new
CREATE2 opcode, instead of the regular
CREATE opcode (which would be invoked by using
pair = new UniswapV2Pair()).
The benefit of using
CREATE2 is that the contract address doesn't depend on the transaction nonce, but on other values which do not automatically change. This way the address can be predetermined.
One of the main advantages of predetermined addresses is that the contract only needs to be created if needed - this is the case especially for Layer 2 disputes where the contract is actually created only if a dispute arises and it needs to be resolved with the contract. This way we save in gas costs.
In the case of Uniswap, I've understood they use
CREATE2 also due to gas savings; the creation is cheaper. I don't fully understand the system so I Can't much comment on that, but that's what I have been told.
In newer Solidity versions assembly is not needed but
CREATE2 can be invoked directly from pure Solidity. Here's some more information: https://docs.openzeppelin.com/cli/2.8/deploying-with-create2