Of course it's possible. However, it will take significantly more CPU resources than having a UART do all the low level timing for you.
Transmitting is easier than receiving because you own the clock. You know when the leading edge of the start bit is, so you don't have to do any sub-bit timing.
For receiving, you have to synchronize to the leading edge of the start bit. A method I used once is to interrupt on the falling edge when not in a character. This then sets up a timer to interrupt in the middle of subsequent bits. Note that the first interrupt period is 1½ bit times and the remaining intervals 1 bits times. If you know the interrupt latency, you can compensate for it by loading the timer with a shorter value. In the interrupt for the last bit, you turn off the timer interrupt and re-enable the falling edge interrupt, which arms the system ready to receive the next byte.
There are also external UART chips. These can interface over IIC, SPI, or parallel lines. That takes more hardware, but a lot less CPU.
There are lots of methods, each with its own tradeoffs between criteria.