Alternatively to Mikahil Vladimirovs answere, you could also implement a bytecode interpreter smart contract, which will parse the bytes within a loop, determine the opcodes and following data and finally execute the relevant EVM instructions in YUL code. For complete functionality, the interpreter smart contract must be called using "delegatecall".
I think this solution requires less gas for small sequences of instructions, whereas Mikhail Vladimirovs solution is more gas efficient for bigger sequences of instructions. One ethical concern in regards to Mikhail Vladimirovs solution is that it bloats the storage trie with zombie smart contracts, which every full node in the decentralized network has to carry.
EDIT: Using CREATE2 to create the contracts you can ensure that the same bytecode is not deployed twice. There will still be a lot of zombie contracts, but at least you can reuse a contract for the same bytecode.
Opcodes: https://github.com/crytic/evm-opcodes
YUL EVM Dialect: https://solidity.readthedocs.io/en/v0.6.3/yul.html#evm-dialect